package com.project.thisDatabase.base.service.impl;

import com.google.gson.reflect.TypeToken;
import com.project.thisCommon.common.ConvertEntity;
import com.project.thisDatabase.base.DbExecutorBase;
import com.project.thisDatabase.base.db.SqlText;
import com.project.thisDatabase.base.mapper.BaseMapper;
import com.project.thisDatabase.base.mapper.BaseViewMapper;
import com.project.thisDatabase.base.model.EntityBase;
import com.project.thisDatabase.base.model.EntityPageBase;
import com.project.thisDatabase.base.model.UserInfoEntity;
import com.project.thisDatabase.base.model.data.Condition;
import com.project.thisDatabase.base.model.entities.IntResultEntity;
import com.project.thisDatabase.base.model.entities.PageEntity;
import com.project.thisDatabase.base.service.ContextInterfaceBase;
import com.project.thisDatabase.base.service.ServiceViewInterfaceBase;
import org.springframework.beans.factory.annotation.Autowired;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public abstract class ServiceViewBase<T extends EntityBase,M extends BaseViewMapper<T>> implements ServiceViewInterfaceBase<T> {

    @Autowired(required = false)
    protected DbExecutorBase dbExecutorBase;

    @Autowired
    protected SqlText sqlText;

    @Autowired
    protected ContextInterfaceBase contextInterfaceBase;

    @Autowired
    protected M mapper;

    @Override
    public List<T> search(T entity){
        return mapper.search(entity);
    }

    @Override
    public List<T> searchPage(EntityPageBase<T> entity){
        Map<String,Object> map=createPageEntity(entity);
        return mapper.searchPage((T)map.get("entityItem"),(PageEntity)map.get("pageItem"));
    }

    @Override
    public IntResultEntity count(T entity) {
        return mapper.count(entity);
    }

    @Override
    public IntResultEntity countAut(T entity) {
        UserInfoEntity loginUserItem = contextInterfaceBase.userInfo();
        if(null != loginUserItem) {
            entity.setOwnId(loginUserItem.getId());
            return mapper.countAut(entity);
        }

        return null;
    }

    @Override
    public List<T> searchAut(T entity){
        UserInfoEntity loginUserItem = contextInterfaceBase.userInfo();
        if(null != loginUserItem) {
            entity.setOwnId(loginUserItem.getId());
            return mapper.searchAut(entity);
        }

        return null;
    }

    @Override
    public List<T> searchPageAut(EntityPageBase<T> entity){
        UserInfoEntity loginUserItem = contextInterfaceBase.userInfo();
        if(null != loginUserItem) {
            entity.getData().setOwnId(loginUserItem.getId());
            Map<String,Object> map=createPageEntity(entity);
            return mapper.searchPageAut((T)map.get("entityItem"),(PageEntity)map.get("pageItem"));
        }

        return null;
    }

    @Override
    public <U> List<T> search(Condition<U> item) throws Exception {
        return search(item, null);
    }

    @Override
    public <U> List<T> search(Condition<U> item, PageEntity page) throws Exception {
        return search(new String[] {"*"}, item, page);
    }

    @Override
    public <U> List<T> search(String[] cols, Condition<U> item, PageEntity page) throws Exception {
        T en = newInstance(item.getBody().getClass().newInstance());
        List pm = new ArrayList();
        Integer start = null, max = null;
        if (null != page) {
            start = page.getPageIndex();
            max = page.getPageSize();
        }
        String sql = sqlText.Select(cols, item, start, max, pm);
        List<T> ls = dbExecutorBase.search(sql, pm, en.getClass());

        return ls;
    }

    protected T newInstance(Object obj) {
        Type tp = ((ParameterizedType)this.getClass().getGenericSuperclass()).getActualTypeArguments()[0];
//        Type tp = new TypeToken<T>() {}.getType();
        try {
            T res = ConvertEntity.copyEntity(obj, tp);
            return res;
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

    protected Map<String,Object> createPageEntity(EntityPageBase<T> form) {
        Map<String,Object> map = new HashMap<String,Object>();
        T entity = newInstance(form.getData());
        map.put("entityItem", entity);
        map.put("pageItem", form.getPageEntity());
        return map;
    }

}
